Skip to content

chore: Add NetworkObject ownership docs and update related docs#3879

Draft
EmandM wants to merge 2 commits intodevelop-2.0.0from
chore/update-ownership-documentation
Draft

chore: Add NetworkObject ownership docs and update related docs#3879
EmandM wants to merge 2 commits intodevelop-2.0.0from
chore/update-ownership-documentation

Conversation

@EmandM
Copy link
Member

@EmandM EmandM commented Feb 24, 2026

Purpose of this PR

At long last.... Ownership docs!

Jira ticket

Link to related jira ticket (Use the smart commits). Short version (e.g. MTT-123) also works and gets auto-linked

Changelog

  • Added: The package whose Changelog should be added to should be in the header. Delete the changelog section entirely if it's not needed.
  • Fixed: If you update multiple packages, create a new section with a new header for the other package.
  • Removed/Deprecated/Changed: Each bullet should be prefixed with Added, Fixed, Removed, Deprecated, or Changed to indicate where the entry should go.

Documentation

  • No documentation changes or additions were necessary.
  • Includes documentation for previously-undocumented public API entry points.
  • Includes edits to existing public API documentation.

Testing & QA (How your changes can be verified during release Playtest)

Functional Testing

Manual testing :

  • Manual testing done

Automated tests:

  • Covered by existing automated tests
  • Covered by new automated tests

Does the change require QA team to:

  • Review automated tests?
  • Execute manual tests?
  • Provide feedback about the PR?

If any boxes above are checked the QA team will be automatically added as a PR reviewer.

Backports

Copy link
Member

@NoelStephensUnity NoelStephensUnity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made a few suggestions... otherwise it looks great (and was definitely needed).

To see if the server owns a NetworkObject, you can check the [`NetworkObject.IsOwnedByServer`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.IsOwnedByServer.html) or the [`NetworkBehaviour.IsOwnedByServer`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkBehaviour.IsOwnedByServer.html) property.

> [!NOTE]
> When you want a specific NetworkObject to keep existing after the owner leaves the session, you can set the `NetworkObject.DontDestroyWithOwner` property to `true`. This ensures that the owned NetworkObject isn't destroyed as the owner leaves.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are some suggested adjustments:
To assure a spawned NetworkObject persists after the owner leaves a session, set the NetworkObject.DontDestroyWithOwner property to true. This assures the client-owned NetworkObject doesn't get destroyed when the owning client leaves.

Comment on lines +12 to +14
## Authority ownership

If you're creating a client-server game and you want a client to control more than one NetworkObject, or if you're creating a distributed authority game and the authority/current owner of the object would like to change ownership, use the following ownership methods.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ownership vs authority

The client-server and distributed authority network topologies have slight differences when it comes to ownership and authority.

  • Client-server: A client can own a spawned NetworkObject but the server always maintains spawn authority over the NetworkObject. Ownership only provides the owning client authority over NetworkVariables (with write permissions), any NetworkTransform configured for owner authority, and can be used to send an RPC that targets the owner.
  • Distributed authority: If a client owns a NetworkObject it becomes the "over-all" authority of that NetworkObject. This means the owning client has spawn/de-spawn authority, write permissions to NetworkVariables (associated with the owned NetworkObject), the motion authority (if the NetworkObject has any NetworkTransforms), and the owning client can change the ownership permissions flags.

The following methods change their behavior based on the network topology being used:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, except one day Noel will learn that it's 'overall' not 'over-all'

Comment on lines +16 to +20
The default `NetworkObject.Spawn` method will set server-side ownership when using a client-server topology. When using a distributed authority topology, this method will set the client who calls the method as the owner.

```csharp
GetComponent<NetworkObject>().Spawn();
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetworkObject.Spawn

  • Client-Server: The server defaults as the owner of this spawned object.
  • Distributed authority: The client invoking this method becomes the owner of the spawned object.

```csharp
GetComponent<NetworkObject>().ChangeOwnership(clientId);
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetworkObject.SpawnWithOwnership

  • Client-Server: The client identifier passed in as a parameter defines who the owner will be.
  • Distributed authority: It is not recommended to use this method when using distributed authority if there are initial settings you want applied when spawning the new instance. For this scenario, it is recommended to use NetworkObject.Spawn, allow the settings to be applied locally, and then use NetworkObject.ChangeOwnership.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved SpawnWithOwnership to the bottom of the page. That way ChangeOwnership has a higher prominence than SpawnWithOwnership, hopefully leading to fewer SpawnAuthority issues.

Comment on lines +117 to +135
internal class MyRequestableBehaviour : NetworkBehaviour
{
public override void OnNetworkSpawn()
{
NetworkObject.OnOwnershipRequestResponse = OnOwnershipRequestResponse;
base.OnNetworkSpawn();
}

private void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponseStatus)
{
// Called when the requesting client has gotten a response to their request
}

public override void OnNetworkDespawn()
{
NetworkObject.OnOwnershipRequestResponse = null;
base.OnNetworkDespawn();
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

///


/// When a NetworkObject's permissions includes the
/// flag.
///

public class RequestableOwnershipBehaviour : NetworkBehaviour
{
public override void OnNetworkSpawn()
{
NetworkObject.OnOwnershipRequestResponse += OnOwnershipRequestResponse;
base.OnNetworkSpawn();
}

private void OnOwnershipRequestResponse(NetworkObject.OwnershipRequestResponseStatus ownershipRequestResponseStatus)
{
    switch (ownershipRequestResponseStatus)
    {
        case NetworkObject.OwnershipRequestResponseStatus.Approved:
            {
                // OnOwnershipChanged and OnGainedOwnership is invoked on the client requesting side.
                // OnOwnershipChanged and OnLostOwnership is invoked on the previous owning client side.
                break;
            }
        case NetworkObject.OwnershipRequestResponseStatus.RequestInProgress:
            {
                // Another client already has a request pending.
                break;
            }
        case NetworkObject.OwnershipRequestResponseStatus.CannotRequest:
            {
                // Cannot request means RequestRequired is no longer a permission of this NetworkObject.
                // The owning client changed while the request was being sent.
                break;
            }
        case NetworkObject.OwnershipRequestResponseStatus.Denied:
            {
                // The owning client denied the request.
                break;
            }
        case NetworkObject.OwnershipRequestResponseStatus.Locked:
            {
                // Ownership has been locked by the owning client.
                break;
            }
    }
}

public override void OnNetworkDespawn()
{
    NetworkObject.OnOwnershipRequestResponse -= OnOwnershipRequestResponse;
    base.OnNetworkDespawn();
}

}

To spawn a `NetworkObject` that is [owned](../../terms-concepts/ownership.md) by a different game client than the one doing the spawning, use the following:

```csharp
GetComponent<NetworkObject>().SpawnWithOwnership(clientId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NetworkObject.SpawnWithOwnership(clientId);

### Who can parent NetworkObjects

Similar to [Ownership](../basics/networkobject#ownership), only the server (or host) can control NetworkObject component parenting.
By default, only the [authority](../terms-concepts/authority.md) of an object can change the parenting of the object. This means in a client-server game, only the server (or host) can control NetworkObject component parenting. In a distributed authority game the owner of the object can always parent the object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

owner of the object can always parent the object under any other spawned NetworkObject (owned or not).

In [client-server](client-server.md), ownership behaves as a subset of [authority](./authority.md). The owner of an object can control some aspects of that object, while the authority controls and synchronizes others.

In a distributed authority setting, authority over NetworkObjects isn't bound to a single server, but distributed across clients depending on a NetworkObject's [ownership permission settings](#ownership-permission-settings-distributed-authority-only). NetworkObjects with the distributable permission set are automatically distributed amongst clients as they connect and disconnect.
Ownership provides client-side reactivity. By giving individual clients ownership over objects that are important for their gameplay, clients can locally control some parts of their game. For example, this allows clients to avoid lag in their player controller, while leaving the server as the final game authority.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just remove the space:

Ownership provides client-side reactivity. By giving individual clients ownership


![Distributed authority new client](../images/distributed-authority-new-client.jpg)
**This default behaviour can be changed using the [NetworkVariableWritePermission.Owner](../basics/networkvariable.md#write-permissions)
***This default behaviour can be changed by setting [NetworkObject.AllowOwnerToParent](../advanced-topics/networkobject-parenting.md#who-can-parent-networkobjects)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

|-----------------------------------|----------|-------|
|Spawn/Despawn objects* |Yes |No |
|Change Ownership |Yes |No |
|Move transform** |No |Yes|
|Update NetworkVariables*** |Yes |No |
|Synchronize late joining clients |Yes |No |
|Update object parenting**** |Yes |No |

*The authority when using client-server will always be the server.
**Only when a NetworkTransform's authority mode is set to owner.
***This default behaviour can be changed using the NetworkVariableWritePermission.Owner
****This default behaviour can be changed by setting NetworkObject.AllowOwnerToParent

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, but 'behavior' rather than 'behaviour'

Copy link
Contributor

@jabbacakes jabbacakes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of suggestions here, but it's a lot of new doc 😅 Nothing major, just a lot of wording/style/consistency tweaks.

There are a lot of changes here and it's getting a bit hard to see the wood for the trees, but we'll be rereviewing this content as part of the centralisation efforts so I think it's all good for now.

* [Authority](authority.md)
* [Client-server](client-server.md)
* [Distributed authority](distributed-authority.md)
* [Controlling NetworkObject ownership](../advanced-topics/networkobject-ownership.md)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* [Controlling NetworkObject ownership](../advanced-topics/networkobject-ownership.md)
* [NetworkObject ownership](../advanced-topics/networkobject-ownership.md)

## Overview

If you aren't completely familiar with transform parenting in Unity, then it's highly recommended to [review over the existing Unity documentation](https://docs.unity3d.com/Manual/class-Transform.html) before reading further to properly synchronize all connected clients with any change in a GameObject component's transform parented status, Netcode for GameObjects requires that the parent and child GameObject components have NetworkObject components attached to them.
If you aren't completely familiar with transform parenting in Unity, then it's highly recommended to [review over the existing Unity documentation](https://docs.unity3d.com/Manual/class-Transform.html) before reading further. To properly synchronize all connected clients with any change in a GameObject component's transform parented status, Netcode for GameObjects requires that the parent and child GameObject components have NetworkObject components attached to them. Otherwise, you can use the [AttachableBehaviour](../components/helper/attachablebehaviour.md) and [AttachableNode](../components/helper/attachablenode.md) helper components to synchronize other types of parenting.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If you aren't completely familiar with transform parenting in Unity, then it's highly recommended to [review over the existing Unity documentation](https://docs.unity3d.com/Manual/class-Transform.html) before reading further. To properly synchronize all connected clients with any change in a GameObject component's transform parented status, Netcode for GameObjects requires that the parent and child GameObject components have NetworkObject components attached to them. Otherwise, you can use the [AttachableBehaviour](../components/helper/attachablebehaviour.md) and [AttachableNode](../components/helper/attachablenode.md) helper components to synchronize other types of parenting.
If you aren't familiar with transform parenting in Unity, then it's recommended that you [review the existing Unity documentation](https://docs.unity3d.com/Manual/class-Transform.html) before reading further. To properly synchronize all connected clients with any change in a GameObject component's transform parented status, Netcode for GameObjects requires that the parent and child GameObject components have NetworkObject components attached to them. Otherwise, you can use the [AttachableBehaviour](../components/helper/attachablebehaviour.md) and [AttachableNode](../components/helper/attachablenode.md) helper components to synchronize other types of parenting.

- It's recommended to always use the `NetworkObject.TrySetParent` method when parenting if you plan on changing the `WorldPositionStays` default value.
- Likewise, it's also recommended to use the `NetworkObject.TryRemoveParent` method to remove a parent from a child.
- When a server parents a spawned NetworkObject component under another spawned NetworkObject component during a Netcode game session this parent child relationship replicates across the network to all connected and future late joining clients.
- When an [authority](../terms-concepts/authority.md) parents a spawned NetworkObject component under another spawned NetworkObject component during a Netcode game session this parent child relationship replicates across the network to all connected and future late joining clients.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- When an [authority](../terms-concepts/authority.md) parents a spawned NetworkObject component under another spawned NetworkObject component during a Netcode game session this parent child relationship replicates across the network to all connected and future late joining clients.
- When an [authority](../terms-concepts/authority.md) parents a spawned NetworkObject component under another spawned NetworkObject component during a Netcode game session, this parent-child relationship replicates across the network to all connected and future late-joining clients.

### Who can parent NetworkObjects

Similar to [Ownership](../basics/networkobject#ownership), only the server (or host) can control NetworkObject component parenting.
By default, only the [authority](../terms-concepts/authority.md) of an object can change the parenting of the object. This means in a client-server game, only the server (or host) can control NetworkObject component parenting. In a distributed authority game the owner of the object can always parent the object.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
By default, only the [authority](../terms-concepts/authority.md) of an object can change the parenting of the object. This means in a client-server game, only the server (or host) can control NetworkObject component parenting. In a distributed authority game the owner of the object can always parent the object.
By default, only the [authority](../terms-concepts/authority.md) of a NetworkObject can change the parenting of that NetworkObject.
- In a client-server game, only the server (or host) can control NetworkObject parenting.
- In a distributed authority game, the owner of the NetworkObject can always parent the NetworkObject.

Similar to [Ownership](../basics/networkobject#ownership), only the server (or host) can control NetworkObject component parenting.
By default, only the [authority](../terms-concepts/authority.md) of an object can change the parenting of the object. This means in a client-server game, only the server (or host) can control NetworkObject component parenting. In a distributed authority game the owner of the object can always parent the object.

To allow the [owner](../terms-concepts/ownership.md) to parent their owned object in a client-server game, use the [`NetworkObject.AllowOwnerToParent`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_AllowOwnerToParent) property.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
To allow the [owner](../terms-concepts/ownership.md) to parent their owned object in a client-server game, use the [`NetworkObject.AllowOwnerToParent`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_AllowOwnerToParent) property.
To allow the [owner](../terms-concepts/ownership.md) to parent their owned NetworkObject in a client-server game, use the [`NetworkObject.AllowOwnerToParent`](https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@latest?subfolder=/api/Unity.Netcode.NetworkObject.html#Unity_Netcode_NetworkObject_AllowOwnerToParent) property.

|Move transform |No |**Yes**|
|Update NetworkVariables** |**Yes** |No |
|Synchronize late joining clients|**Yes** |No |
|Update object parenting*** |**Yes** |No |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
|Update object parenting*** |**Yes** |No |
|Update NetworkObject parenting*** |**Yes** |No |


![Distributed authority new client](../images/distributed-authority-new-client.jpg)
**This default behaviour can be changed using the [NetworkVariableWritePermission.Owner](../basics/networkvariable.md#write-permissions)
***This default behaviour can be changed by setting [NetworkObject.AllowOwnerToParent](../advanced-topics/networkobject-parenting.md#who-can-parent-networkobjects)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This, but 'behavior' rather than 'behaviour'

## Ownership in distributed authority

You can also use `NetworkObject.SetOwnershipLock` to lock and unlock the permission settings of a NetworkObject for a period of time, preventing ownership changes on a temporary basis.
In [distributed authority](./distributed-authority.md) the owner of an object is always the authority of that object. In this way, ownership comes before authority. Authority can be transferred between clients via changing and requesting ownership.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In [distributed authority](./distributed-authority.md) the owner of an object is always the authority of that object. In this way, ownership comes before authority. Authority can be transferred between clients via changing and requesting ownership.
In [distributed authority](./distributed-authority.md) the owner of a NetworkObject is always the authority of that NetworkObject. In this way, ownership comes before authority. Authority can be transferred between clients via changing and requesting ownership.


> [!NOTE]
> The ownership permissions are only visible when you have the Multiplayer Services SDK package installed and you're inspecting a NetworkObject within the Editor. Ownership permissions have no impact when using a client-server network topology, because the server always has authority.
When building your game you can use [ownership permissions](../advanced-topics/networkobject-ownership.md#ownership-permissions-settings) to control how and when ownership of objects can be transferred between clients.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When building your game you can use [ownership permissions](../advanced-topics/networkobject-ownership.md#ownership-permissions-settings) to control how and when ownership of objects can be transferred between clients.
When building your game, you can use [ownership permissions](../advanced-topics/networkobject-ownership.md#ownership-permissions-settings) to control how and when ownership of o NetworkObjects can be transferred between clients.

When building your game you can use [ownership permissions](../advanced-topics/networkobject-ownership.md#ownership-permissions-settings) to control how and when ownership of objects can be transferred between clients.

#### Request ownership
Objects with the `OwnershipStatus.Distributable` permission will have their ownership automatically distributed between all connected game clients whenever a new client joins or an existing client leaves. This is the key mechanism in how the game simulation is distributed between clients in a distributed authority session.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Objects with the `OwnershipStatus.Distributable` permission will have their ownership automatically distributed between all connected game clients whenever a new client joins or an existing client leaves. This is the key mechanism in how the game simulation is distributed between clients in a distributed authority session.
NetworkObjects with the `OwnershipStatus.Distributable` permission have their ownership automatically distributed between all connected game clients whenever a new client joins or an existing client leaves. This is the key mechanism in how the game simulation is distributed between clients in a distributed authority session.

Copy link
Contributor

@jabbacakes jabbacakes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of suggestions here, but it's a lot of new doc 😅 Nothing major, just a lot of wording/style/consistency tweaks.

There are a lot of changes here and it's getting a bit hard to see the wood for the trees, but we'll be rereviewing this content as part of the centralisation efforts so I think it's all good for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants